/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package GUI;

import MouseSensorDriver.Calibrator;
import adc_lcard.ADCE140Driver;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.Serializable;
import java.util.Random;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.Timer;

/**
 *
 * @author Asko
 */
public class Experiment implements Serializable {

    private ControlChannel controlChannel;
    private double startPos;
    private double endPos;
    private double factStartPos, factEndPos, mousePos;
    private int factStartSourcePos, factEndSourcePos, mouseSourcePos;
    private long timeReact;
    private double factForce, force;
    private final int forceChannel = 2;
    private Timer scanForce = new Timer(5, new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
            factForce += (Calibrator.get().getData(forceChannel - 1,
                    ADCE140Driver.getGdata(forceChannel)) - factForce) / 20.0;
        }
    });

    public Experiment(ControlChannel controlChannel, double startPos, double endPos) {
        this.controlChannel = controlChannel;
        this.startPos = startPos;
        this.endPos = endPos;
    }

    public void startExperiment(int speed, double aforce) {
        setFeedback(aforce);
        controlChannel.goToPosition(startPos, speed);
        try {
            Thread.sleep(24);
        } catch (InterruptedException ex) {
            Logger.getLogger(Experiment.class.getName()).log(Level.SEVERE, null, ex);
        }
        timeReact = System.currentTimeMillis();
        factStartSourcePos = (int) controlChannel.getSourcePos();
        factStartPos = controlChannel.getCurPos(factStartSourcePos);
        Random r = new Random();
        while (Math.abs(factStartSourcePos - (int) controlChannel.getSourcePos()) < 30
                && System.currentTimeMillis() - timeReact < 213) {
            try {
                Thread.sleep((int) (r.nextDouble() * 200));
            } catch (InterruptedException ex) {
                Logger.getLogger(Experiment.class.getName()).log(Level.SEVERE, null, ex);
            }

        }
        timeReact = System.currentTimeMillis() - timeReact;
//        try {
//            Thread.sleep(100);
//        } catch (InterruptedException ex) {
//            Logger.getLogger(Experiment.class.getName()).log(Level.SEVERE, null, ex);
//        }
        mousePos = controlChannel.getMousePos();
        mouseSourcePos = controlChannel.getSourceMousePos();
        /*factForce = Calibrator.get().getData(forceChannel - 1,
         ADCE140Driver.getGdata(forceChannel));*/
        //controlChannel.startMouseReg();
        //scanForce.start();
        controlChannel.goToPosition(endPos, (int) (speed * (0.50 + (4 - force) / 4.0 * 0.50)));
        //scanForce.stop();
        //controlChannel.endMouseReg();
        factEndSourcePos = (int) controlChannel.getSourcePos();
        factEndPos = controlChannel.getCurPos(factEndSourcePos);
//        try {
//            Thread.sleep(100);
//        } catch (InterruptedException ex) {
//            Logger.getLogger(Experiment.class.getName()).log(Level.SEVERE, null, ex);
//        }
        mousePos = controlChannel.getMousePos() - mousePos;
        mouseSourcePos = controlChannel.getSourceMousePos() - mouseSourcePos;
        

    }

    public ControlChannel getControlChannel() {
        return controlChannel;
    }

    public String getMeasureName() {
        return controlChannel.getMeasureName();
    }

    public double getStartPos() {
        return startPos;
    }

    public double getEndPos() {
        return endPos;
    }

    public double getFactStartPos() {
        return factStartPos;
    }

    public double getFactEndPos() {
        return factEndPos;
    }

    public double getMousePos() {
        return mousePos;
    }

    public int getFactStartSourcePos() {
        return factStartSourcePos;
    }

    public int getFactEndSourcePos() {
        return factEndSourcePos;
    }

    public int getMouseSourcePos() {
        return mouseSourcePos;
    }

    public void setMousePos(double mousePos) {
        this.mousePos = mousePos;
    }

    public double getAbsError() {
        return Math.abs((mousePos - (factEndPos - factStartPos)));
    }

    public double getRelError() {
        return Math.abs((mousePos - (factEndPos - factStartPos)) / (factEndPos - factStartPos));
    }

    public long getTimeReact() {
        return timeReact;
    }

    public double getFactForce() {
        return factForce;
    }

    public double getForce() {
        return force;
    }

    public double getAbsErrorForce() {
        return Math.abs(factForce - force);
    }

    public double getRelErrorForce() {
        return force > 0 ? getAbsErrorForce() / force : -1;
    }

    private void setFeedback(double aforce) {

        force = aforce;
        Random r = new Random();
        if (controlChannel.isMouseSensorX()) {
            factForce = r.nextDouble() * 0.01241;
            //System.out.println("Round motion");
        } else {
            factForce = r.nextDouble() * 0.0235;
            //System.out.println("Line motion");
        }

        if (aforce > 0) {
            //System.out.println("aforce: " + aforce);
            double gran = controlChannel.isMouseSensorX() ? 2 : 4;
            if (aforce > gran) {
                aforce = gran;
            }
            double dforce = aforce - aforce * (0.90 + r.nextDouble() * 0.2);
            while (Math.abs(dforce) > 0.2) {
                dforce *= 0.93;
            }
            factForce = aforce + dforce;
            //System.out.println("factForce: " + factForce);
        }
    }

}
